package com.oromwin.repos;

import org.apache.commons.logging.Log;

import com.oromwin.repos.common.Logger;
import com.oromwin.repos.common.ReposConfig;
import com.oromwin.repos.common.ReposException;
import com.oromwin.repos.http.ReposHttpServer;
import com.oromwin.repos.server.ReposSocketServer;

public class ReposService {
    private Log log = Logger.getLog(ReposService.class);
    private static int waitSeconds = 5000;
    private static String serviceName = ReposService.class.getCanonicalName();
    private static ReposService serviceInstance = new ReposService();
    private static ReposSocketServer socketServer = null;
    private static ReposHttpServer httpServer = null;

    /**
     * @param args
     */
    public static void main(String[] args) {
        String cmd = "start";
        if(args.length > 0) {
            cmd = args[0];
        }
        if (httpServer == null) {
            try {
                httpServer = new ReposHttpServer();
            } catch (ReposException e) {
                e.printStackTrace();
            }
            httpServer.start();
            System.out.println(String.format("HttpServer has started for Unix/Linux Platform '%s'", new java.util.Date().toString()));
        }
        if("start".equals(cmd)) {
            serviceInstance.start();
        } else {
            serviceInstance.stop();
        }
    }

    /**
     * Flag to know if this service
     * instance has been stopped.
     */
    private boolean stopped = false;

    public void start() {
        stopped = false;
        while(!stopped) {
            if (socketServer == null) {
                socketServer = new ReposSocketServer();
                socketServer.start();
                System.out.println(String.format("'%s' has started '%s'", serviceName, new java.util.Date().toString()));
            }
            try {
                Thread.sleep(waitSeconds);
                if (httpServer.hasStopped()) {
                    this.stop();
                    break;
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println(String.format("'%s' has finished '%s'", serviceName, new java.util.Date().toString()));
    }

    public void stop() {
        stopped = true;
        int elapsedTime = 0;
        int status = 0;
        int serverTimeout = ReposConfig.getInstance().getReposSocketServerTimeout();
        ReposSocketServer.setShutdown(stopped);
        int refCount = ReposSocketServer.getRefCount();
        if (log.isInfoEnabled()) log.info(String.format("'%s' has '%d' processing job(s).", serviceName, refCount));
        if (refCount > 0) {
            if (log.isInfoEnabled()) log.info(String.format("'%s' will be shutdown in '%d/%d'ms.", serviceName, elapsedTime, serverTimeout));
            while (refCount > 0 && elapsedTime < serverTimeout) {
                refCount = ReposSocketServer.getRefCount();
                try {
                    if (log.isInfoEnabled()) log.info(String.format("Wating more '%d'sec for running '%d' thread(s).", waitSeconds/1000, refCount));
                    Thread.sleep(waitSeconds);
                    elapsedTime += waitSeconds;
                } catch (InterruptedException e) {
                    System.err.println(String.format("Failed to stop '%s' for '%s'", serviceName, e.getMessage()));
                    e.printStackTrace();
                    status = -1;
                }
            }
        } else {
            try {
                if (log.isInfoEnabled()) log.info(String.format("Wating more '%d'sec until main thread has stopped.", waitSeconds/1000));
                Thread.sleep(waitSeconds);
            } catch (InterruptedException e) {
                System.err.println(String.format("Failed to stop '%s' for '%s'", serviceName, e.getMessage()));
                e.printStackTrace();
                status = -2;
            }
        }
        if (log.isInfoEnabled()) log.info(String.format("'%s' has stopped successfully.", serviceName, serverTimeout));
        System.exit(status);
    }
}
